from datetime import datetime
from typing import Optional, List
import aiomysql
import aiohttp

from http.client import HTTPException
from fastapi import HTTPException
from fastapi import APIRouter
from fastapi import Query
from pydantic import BaseModel

from apps.utils.sql_conn import get_db_cursor

medic = APIRouter()


#  医药类模型
#  药品信息模型
class DrugItem(BaseModel):
    type: int
    drugName: Optional[str] = None
    price: Optional[float] = None
    syz: Optional[str] = None
    pzwh: Optional[str] = None


class BillCreateRequest(BaseModel):
    email: str
    money: float
    detail: str


class BillItem(BaseModel):
    id: Optional[int] = None
    email: str
    detail: str
    money: float
    buy_time: Optional[str] = None


path = "/tmcx/drug/query"


class DrugQueryRequsest(BaseModel):
    key: str


# 药品系列接口
@medic.get("/medic/drugs_by_type",
           response_description="根据type查询药品信息",
           response_model=List[DrugItem])
async def get_drugs_by_type(
        type: int = Query(..., ge=1, le=10, description="药品类型（1-10之间的整数）")
):
    try:
        async with get_db_cursor() as cursor:
            await cursor.execute(
                "SELECT type, drugName, price, syz, pzwh FROM drug_medicine WHERE type = %s",
                (type,)
            )

            drugs = await cursor.fetchall()

            result = []
            for drug in drugs:
                if isinstance(drug, dict):
                    drug_item = DrugItem(
                        type=drug.get("type"),
                        drugName=drug.get("drugName"),
                        price=drug.get("price"),
                        syz=drug.get("syz"),
                        pzwh=drug.get("pzwh")
                    )
                else:
                    drug_item = DrugItem(
                        type=drug[0],
                        drugName=drug[1],
                        price=drug[2],
                        syz=drug[3],
                        pzwh=drug[4]
                    )
                result.append(drug_item)

            return result

    except aiomysql.Error as e:
        error_code = e.args[0]
        error_msg = e.args[1]
        raise HTTPException(
            status_code=500,
            detail=f"数据库查询失败：{error_msg}（错误代码：{error_code}）"
        )
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"接口处理异常：{str(e)}"
        )


@medic.get("/medic/drugs_by_pzwh", response_description="根据国药准字查询药品信息")
async def get_drugs_by_pzwh(
        pzwh: str = Query(..., description="药品批准文号（如：国药准字H13023635）")
):
    host = "https://jumbarcode.market.alicloudapi.com"
    appcode = '97f15fedc05e4020ae11be8931545a5b'
    headers = {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Authorization": "APPCODE " + appcode
    }
    path = "/tmcx/drug/detail"
    url = host + path
    bodys = {"pzwh": pzwh}

    try:
        async with aiohttp.ClientSession() as session:
            async with session.post(url, data=bodys, headers=headers) as response:
                if response.status != 200:
                    raise HTTPException(
                        status_code=response.status,
                        detail=f"阿里云接口返回非成功状态码：{response.status}"
                    )
                return await response.json()  # 直接返回原始响应
    except aiohttp.ClientError as e:
        raise HTTPException(
            status_code=500,
            detail=f"调用阿里云药品查询API失败：{str(e)}"
        )


@medic.post("/medic/query", response_description="阿里云药品查询接口（自动区分准字号查询）")
async def query_drug_info(request: DrugQueryRequsest):
    # 基础配置
    host = "https://jumbarcode.market.alicloudapi.com"
    appcode = '97f15fedc05e4020ae11be8931545a5b'
    headers = {
        "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
        "Authorization": "APPCODE " + appcode
    }

    if "国药准字" in request.key:
        path = "/tmcx/drug/detail"
        bodys = {"pzwh": request.key}
    else:
        path = "/tmcx/drug/query"
        bodys = {
            "key": request.key,
            "type": "1",
            "pageNo": "1"
        }

    url = host + path

    try:
        async with aiohttp.ClientSession() as session:
            async with session.post(url, data=bodys, headers=headers) as response:
                if response.status != 200:
                    raise HTTPException(
                        status_code=response.status,
                        detail=f"阿里云接口返回非成功状态码：{response.status}"
                    )
                return await response.json()
    except aiohttp.ClientError as e:
        raise HTTPException(
            status_code=500,
            detail=f"调用阿里云药品查询API失败：{str(e)}"
        )


@medic.post("/medic/create_bill",
            response_description="创建账单记录",
            response_model=BillItem)
async def create_bill(request: BillCreateRequest):
    try:
        async with get_db_cursor() as cursor:
            await cursor.execute(
                "SELECT email FROM user_info WHERE email = %s",
                (request.email,)
            )
            user = await cursor.fetchone()
            if not user:
                raise HTTPException(
                    status_code=404,
                    detail=f"user_info表中不存在该email：{request.email}"
                )

            await cursor.execute(
                """INSERT INTO bill (email, detail, money, buy_time) 
                   VALUES (%s,%s,%s, NOW())""",
                (request.email, request.detail, request.money)
            )

            await cursor.execute("SELECT LAST_INSERT_ID() AS bill_id")  # 给结果起别名，方便字典访问
            result = await cursor.fetchone()

            if not result:
                raise HTTPException(status_code=500, detail="获取账单ID失败，未查询到结果")

            # 兼容元组（[0]）和字典（['bill_id']）格式
            bill_id = result[0] if isinstance(result, (tuple, list)) else result.get('bill_id')

            if bill_id is None:
                raise HTTPException(status_code=500, detail="获取账单ID失败，结果为空")

        return BillItem(
            id=bill_id,
            email=request.email,
            detail=request.detail,
            money=request.money,
            buy_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        )
    except aiomysql.Error as e:
        await cursor.connection.rollback()
        error_code = e.args[0]
        error_msg = e.args[1]
        raise HTTPException(
            status_code=500,
            detail=f"数据库操作失败：{error_msg}（错误代码：{error_code}）"
        )
    except HTTPException as e:
        raise e

@medic.get("/medic/purchase_records",
           response_description="查询个人买药记录",
           response_model=List[dict])
async def get_purchase_records(
        email: str = Query(..., description="用户邮箱，用于查询对应的买药记录")
):
    try:
        async with get_db_cursor() as cursor:
            # 查询bill表中该邮箱对应的所有记录
            await cursor.execute(
                "SELECT detail, money, buy_time FROM bill WHERE email = %s",
                (email,)
            )
            records = await cursor.fetchall()

            # 处理查询结果，封装成指定格式
            result = []
            for record in records:
                if isinstance(record, dict):
                    # 字典类型直接取值
                    record_dict = {
                        "detail": record.get("detail"),
                        "money": record.get("money"),
                        "buy_time": record.get("buy_time")
                    }
                else:
                    # 元组类型按索引取值
                    record_dict = {
                        "detail": record[0],
                        "money": record[1],
                        "buy_time": record[2]
                    }
                result.append(record_dict)

            # 返回整体封装在数组中的结果
            return result

    except aiomysql.Error as e:
        error_code = e.args[0]
        error_msg = e.args[1]
        raise HTTPException(
            status_code=500,
            detail=f"数据库查询失败：{error_msg}（错误代码：{error_code}）"
        )
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"接口处理异常：{str(e)}"
        )